package com.snails.net.manager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;

import com.snails.net.utils.NetworkUtil;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import static android.content.Context.CONNECTIVITY_SERVICE;

/**
 * 网络变化管理监听器
 *
 * @author lawrence
 * @date 2019-04-08
 */

public final class NetworkChangedManager {
    private Context ctx = null;
    // android 7.0 (24) 之下版本
    private NetworkChangeReceiver networkChangeReceiver = null;
    // android 7.0 (24) 之上
    private ConnectivityManager connectivityManager = null;
    private Object networkCallback = null;

    private Set<OnNetworkStateChangedCallback> callbacks = null;

    public NetworkChangedManager(Context ctx) {
        this.ctx = ctx;
        this.callbacks = new HashSet<>();
    }

    /**
     * 添加网络状态监听
     *
     * @param callback
     */
    public void addCallback(OnNetworkStateChangedCallback callback) {
        if (this.callbacks == null) {
            this.callbacks = new HashSet<>();
        }
        if (!this.callbacks.contains(callback)) this.callbacks.add(callback);
    }

    /**
     * 移除网络状态监听
     *
     * @param callback
     */
    public void removeCallback(OnNetworkStateChangedCallback callback) {
        if (this.callbacks != null && this.callbacks.contains(callback)) {
            this.callbacks.remove(callback);
        }
    }

    /**
     * 获得当前网络连接状态
     *
     * @return true-已连接，false-未连接
     */
    public boolean isConnected() {
        if (NetworkUtil.getCtx() == null) {
            NetworkUtil.init(this.ctx);
        }
        return NetworkUtil.instance().isConnected();
    }

    /**
     * 注册网络监听器
     */
    public void register() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager = (ConnectivityManager) this.ctx.getSystemService(CONNECTIVITY_SERVICE);
            NetworkRequest request = new NetworkRequest.Builder()
                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                    .build();
            final ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) { onNotifyAll(true); }
                @Override
                public void onLost(Network network) { onNotifyAll(false); }
            };
            networkCallback = callback;
            connectivityManager.requestNetwork(request, callback);
        } else {
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            networkChangeReceiver = new NetworkChangeReceiver();
            this.ctx.registerReceiver(networkChangeReceiver, intentFilter);
        }
    }

    /**
     * 注销网络监听器
     */
    public void unregister() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (connectivityManager != null
                    && networkCallback instanceof ConnectivityManager.NetworkCallback) {
                final ConnectivityManager.NetworkCallback callback
                        = (ConnectivityManager.NetworkCallback) networkCallback;
                connectivityManager.unregisterNetworkCallback(callback);
            }
            connectivityManager = null;
        } else {
            if (networkChangeReceiver != null) {
                this.ctx.unregisterReceiver(networkChangeReceiver);
            }
            networkChangeReceiver = null;
        }

        if (callbacks != null) callbacks.clear();
    }

    /**
     * 通知所有订阅者状态改变
     *
     * @param isConnected true-网络已连接，false-网络已断开
     */
    private void onNotifyAll(boolean isConnected) {
        if (NetworkChangedManager.this.callbacks != null) {
            Iterator<OnNetworkStateChangedCallback> iterator
                    = NetworkChangedManager.this.callbacks.iterator();
            while (iterator.hasNext()) {
                final OnNetworkStateChangedCallback callback = iterator.next();
                if (callback != null) callback.onCallback(isConnected);
            }
        }
    }

    /**
     * android 7.0 (24) 之下版本
     */
    private class NetworkChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
                final boolean isConnected = NetworkChangedManager.this.isConnected();
                NetworkChangedManager.this.onNotifyAll(isConnected);
            }
        }
    }

    /**
     * 网络状态监听回调
     */
    public static abstract class OnNetworkStateChangedCallback {
        // 历史网络连接状态, 默认true-已连接
        private boolean isConnected = true;

        /**
         * 网络变化回调
         *
         * @param isConnected true-网络已连接，false-网络不可用
         */
        public void onCallback(boolean isConnected) {
            if (this.isConnected != isConnected) {
                this.isConnected = isConnected;
                onStateChanged(this.isConnected);
            }
        }

        public abstract void onStateChanged(boolean isConnected);
    }

}
